"""
生成器

生成器作用：
    根据程序设计者制定的规则循环生成数据，当条件不成立时则生成数据结束
    数据不是一次性全部生成出来，而是使用一个，生成一个，可以节约大量内存

创建生成器的两种方式：
    1.生成器推导式：
        与列表推导式类似，只不过生成器推导式使用小括号
        e.g. g = (i * 2 for i in range(5))

    2.yield关键字：
        在函数中具有yield关键字
        PS:
            2.1代码运行到yield会暂停，然后把结果返回出去，下次启动生成器会在暂停位置继续往下执行
            2.2生成器如果把数据生成完成，再次获取生成器中的下一个数据会抛出StopIteration异常，表示停止迭代异常
            2.3while循环内部没有处理异常操作，需要手动添加处理异常操作
            2.4for循环内部自动处理了停止迭代异常，使用起来更加方便，推荐使用

    3.生成器相关函数：
        - next函数获取生成器中的下一个值
        - for循环遍历生成器中的每一个值
"""


def func(num):
    for i in range(num):
        print("开始生成...")
        yield i
        print("完成一次...")


g = func(5)


# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))

# while True:
#     try:
#         print(next(g))
#     except StopIteration:
#         break

# for i in g:
#     print(i)


def fibonacci(n):
    """生成斐波那契"""
    num1, num2 = 1, 1
    for i in range(n):
        yield num1
        num1, num2 = num2, num1 + num2


for i in fibonacci(10):
    print(i, end=' ')
